package math

import (
	"cmp"
	"golang.org/x/exp/constraints"
	"math"
)

type digit interface {
	~int | ~int32 | ~int64 | ~float64
}

func InBetween[T cmp.Ordered](needle T, min T, max T) bool {
	return needle >= min && needle <= max
}

func InRange[T cmp.Ordered](needle T, min T, max T) bool {
	return needle > min && needle < max
}

// Min 返回最小值
func Min[T constraints.Ordered](values ...T) T {
	var minVal T
	for i, v := range values {
		if i == 0 {
			minVal = v
		} else if v < minVal {
			minVal = v
		}
	}

	return minVal
}

// Max 返回最大值
func Max[T constraints.Ordered](values ...T) T {
	var maxVal T
	for i, v := range values {
		if i == 0 {
			maxVal = v
		} else if maxVal < v {
			maxVal = v
		}
	}

	return maxVal
}

// Round 四舍五入, 默认保留两位小数
func Round(value float64, digits ...int64) float64 {
	_digits := int64(2)
	if len(digits) > 0 {
		_digits = digits[0]
	}

	if _digits < 0 {
		_digits = 0
	}

	return math.Round(value*math.Pow(10, float64(_digits))) / math.Pow(10, float64(_digits))
}

// KeepHighestTwoDigits 保留最高两位数字, 其余位置0, 例如 12345 -> 12000
func KeepHighestTwoDigits(n int64) int64 {
	// 如果数字小于 100，直接返回
	if n < 100 {
		return n
	}

	// 计算数字的位数
	numDigits := int(math.Log10(float64(n))) + 1

	// 计算需要的除数：10^(位数 - 2)
	divisor := int64(math.Pow(10, float64(numDigits-2)))

	// 获取最高的两位数字
	highestTwo := n / divisor

	// 将其余位设置为 0
	result := highestTwo * divisor

	return result
}

// KeepHighestOneDigit 保留最高一位数字, 其余位置0, 例如 789 -> 700
func KeepHighestOneDigit(n int64) int64 {
	// 如果数字小于 10，直接返回
	if n < 10 {
		return n
	}

	// 计算数字的位数
	numDigits := int(math.Log10(float64(n))) + 1

	// 计算需要的除数：10^(位数 - 1)
	divisor := int64(math.Pow(10, float64(numDigits-1)))

	// 获取最高的一位数字
	highestOne := n / divisor

	// 将其余位设置为 0
	result := highestOne * divisor

	return result
}

func SumWithRatio(values map[float64]float64) float64 {
	var sum float64

	for value, ratio := range values {
		sum += value * ratio
	}

	return sum
}

func Abs[T constraints.Integer | constraints.Float](value T) T {
	if value < 0 {
		return -value
	}

	return value
}
